package com.ZeroCarbon.service.impl;

import com.ZeroCarbon.client.UserClient;
import com.ZeroCarbon.domain.po.Good;
import com.ZeroCarbon.domain.po.Order;
import com.ZeroCarbon.exception.BusinessLogicException;
import com.ZeroCarbon.mapper.OrderMapper;
import com.ZeroCarbon.service.IOrderService;
import com.ZeroCarbon.utils.UserHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import lombok.RequiredArgsConstructor;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.List;

import static com.ZeroCarbon.exception.BusinessLogicException.ERROR_EXCEPTION;
import static com.ZeroCarbon.prefix.MySqlKey.ORDER_PREFIX;
import static com.ZeroCarbon.prefix.MySqlKey.generateId;

@Service
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    private final UserClient userClient;

    private final RedissonClient redisson;

    /**
     * 保存订单
     *
     * @param order 订单信息
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrder(Order order) throws BusinessLogicException {
        //获取用户id
        String userId = UserHolder.getUser();
        //生成id
        String id = generateId(ORDER_PREFIX);

        //设置订单信息
        order.setId(id)
                .setUserId(userId)
                .setPayTime(LocalDate.now());
        //锁对象
        RLock lock = null;
        try {
            //获取出售商品
            Good good = Db.lambdaQuery(Good.class)
                    .eq(Good::getId, order.getGoodsId())
                    .one();
            //根据商品id创建锁
            lock = redisson.getLock("product_lock:" + good.getId());
            //采用看门狗机制自动续期
            lock.lock();
            //商品减去库存
            boolean updateStock = Db.lambdaUpdate(Good.class)
                    .setSql("number = number - {0}", order.getNumber())
                    .ge(Good::getNumber, order.getNumber())     //乐观锁，双重保证不超卖
                    .update();
            //如果更新失败则说明库存不足
            if (!updateStock) {
                throw new BusinessLogicException("商品库存不足");
            }
            //获取出售者id
            String sellerId = good.getUserId();
            //出售者获取报酬
            userClient.addMoneyAndIntegral(sellerId, good.getPrice(), good.getIntegral());
            //保存订单信息
            if (!save(order)) {
                throw new BusinessLogicException();
            }
        } catch (Exception e) {
            throw new BusinessLogicException(e.getMessage());
        } finally {
            //如果锁被加锁线程所持有则进行解锁
            if (lock != null && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 获取订单
     */
    @Override
    public List<Order> getOrder() throws BusinessLogicException {
        //获取用户id
        String userId = UserHolder.getUser();
        //订单构造器
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, userId);
        try {
            //获取订单列表
            return list(wrapper);
        } catch (Exception e) {
            throw new BusinessLogicException(ERROR_EXCEPTION);
        }
    }
}
